{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Configurations for Colab"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 1,
   "metadata": {},
   "outputs": [],
   "source": [
    "import sys\n",
    "IN_COLAB = 'google.colab' in sys.modules\n",
    "\n",
    "if IN_COLAB:\n",
    "    !apt-get install -y xvfb python-opengl > /dev/null 2>&1\n",
    "    !pip install gym pyvirtualdisplay > /dev/null 2>&1\n",
    "    !pip install JSAnimation==0.1\n",
    "    \n",
    "    from pyvirtualdisplay import Display\n",
    "    \n",
    "    # Start virtual display\n",
    "    dis = Display(visible=0, size=(400, 400))\n",
    "    dis.start()"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# 01. DQN\n",
    "\n",
    "[V. Mnih et al., \"Human-level control through deep reinforcement learning.\" Nature, 518\n",
    "(7540):529–533, 2015.](https://storage.googleapis.com/deepmind-media/dqn/DQNNaturePaper.pdf)\n",
    "\n",
    "Reinforcement learning is known to be unstable or even to diverge when a nonlinear function approximator such as a neural network is used to represent the action-value (also known as $Q$) function. This instability has several causes: the correlations present in the sequence of observations, the fact that small updates to $Q$ may significantly change the policy and therefore change the data distribution, and the correlations between the action-values ($Q$) and the target values $r + \\gamma \\max_{a'} Q(s', a')$.\n",
    "\n",
    "The authors suggest two key ideas to address these instabilities with a novel variant of Q-learning: Replay buffer and Fixed Q-target.\n",
    "\n",
    "#### Uniformly random sampling from Experience Replay Memory\n",
    "\n",
    "Reinforcement learning agent stores the experiences consecutively in the buffer, so adjacent ($s, a, r, s'$) transitions stored are highly likely to have correlation. To remove this, the agent samples experiences uniformly at random from the pool of stored samples $\\big( (s, a, r, s') \\sim U(D) \\big)$. See sample_batch method of ReplayBuffer class for more details.\n",
    "\n",
    "#### Fixed Q-target\n",
    "\n",
    "DQN uses an iterative update that adjusts the action-values ($Q$) towards target values that are only periodically updated, thereby reducing correlations with the target; if not, it is easily divergy because the target continuously moves. The Q-learning update at iteration $i$ uses the following loss function:\n",
    "\n",
    "$$\n",
    "L_i(\\theta_i) = \\mathbb{E}_{(s,a,r,s') \\sim U(D)} \\big[ \\big( r + \\gamma \\max_{a'} Q(s',a';\\theta_i^-) - Q(s, a; \\theta_i) \\big)^2 \\big]\n",
    "$$\n",
    "\n",
    "in which $\\gamma$ is the discount factor determining the agent’s horizon, $\\theta_i$ are the parameters of the Q-network at iteration $i$ and $\\theta_i^-$ are the network parameters used to compute the target at iteration $i$. The target network parameters $\\theta_i^-$ are only updated with the Q-network parameters ($\\theta_i$) every C steps and are held fixed between individual updates. ($C = 200$ in CartPole-v0)\n",
    "\n",
    "#### For more stability: Gradient clipping\n",
    "\n",
    "The authors also found it helpful to clip the error term from the update $r + \\gamma \\max_{a'} Q(s', a'; \\theta_i^-) - Q(s,a,;\\theta_i)$ to be between -1 and 1. Because the absolute value loss function $|x|$ has a derivative of -1 for all negative values of x and a derivative of 1 for all positive values of x, clipping the squared error to be between -1 and 1 corresponds to using an absolute value loss function for errors outside of the (-1,1) interval. This form of error clipping further improved the stability of the algorithm."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "metadata": {},
   "outputs": [],
   "source": [
    "import os\n",
    "from typing import Dict, List, Tuple\n",
    "\n",
    "import gym\n",
    "import matplotlib.pyplot as plt\n",
    "import numpy as np\n",
    "import torch\n",
    "import torch.nn as nn\n",
    "import torch.optim as optim\n",
    "from IPython.display import clear_output\n",
    "from torch.nn.utils import clip_grad_norm_"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Replay buffer\n",
    "\n",
    "Typically, people implement replay buffers with one of the following three data structures:\n",
    "\n",
    "  - collections.deque\n",
    "  - list\n",
    "  - numpy.ndarray\n",
    "  \n",
    "**deque** is very easy to handle once you initialize its maximum length (e.g. deque(maxlen=buffer_size)). However, the indexing operation of deque gets terribly slow as it grows up because it is [internally doubly linked list](https://wiki.python.org/moin/TimeComplexity#collections.deque). On the other hands, **list** is an array, so it is relatively faster than deque when you sample batches at every step. Its amortized cost of  *Get item* is [O(1)](https://wiki.python.org/moin/TimeComplexity#list).\n",
    "\n",
    "Last but not least, let's see **numpy.ndarray**. numpy.ndarray is even faster than list due to the fact that it is [a homogeneous array of fixed-size items](https://docs.scipy.org/doc/numpy/reference/generated/numpy.ndarray.html#numpy.ndarray), so you can get the benefits of [locality of reference](https://en.wikipedia.org/wiki/Locality_of_reference). Whereas list is an array of pointers to objects, even when all of them are of the same type.\n",
    "\n",
    "Here, we are going to implement a replay buffer using numpy.ndarray.\n",
    "\n",
    "\n",
    "Reference: [OpenAI spinning-up](https://github.com/openai/spinningup/blob/master/spinup/algos/sac/sac.py#L10)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "metadata": {},
   "outputs": [],
   "source": [
    "class ReplayBuffer:\n",
    "    \"\"\"A simple numpy replay buffer.\"\"\"\n",
    "\n",
    "    def __init__(self, obs_dim: int, size: int, batch_size: int = 32):\n",
    "        self.obs_buf = np.zeros([size, obs_dim], dtype=np.float32)\n",
    "        self.next_obs_buf = np.zeros([size, obs_dim], dtype=np.float32)\n",
    "        self.acts_buf = np.zeros([size], dtype=np.float32)\n",
    "        self.rews_buf = np.zeros([size], dtype=np.float32)\n",
    "        self.done_buf = np.zeros(size, dtype=np.float32)\n",
    "        self.max_size, self.batch_size = size, batch_size\n",
    "        self.ptr, self.size, = 0, 0\n",
    "\n",
    "    def store(\n",
    "        self,\n",
    "        obs: np.ndarray,\n",
    "        act: np.ndarray, \n",
    "        rew: float, \n",
    "        next_obs: np.ndarray, \n",
    "        done: bool,\n",
    "    ):\n",
    "        self.obs_buf[self.ptr] = obs\n",
    "        self.next_obs_buf[self.ptr] = next_obs\n",
    "        self.acts_buf[self.ptr] = act\n",
    "        self.rews_buf[self.ptr] = rew\n",
    "        self.done_buf[self.ptr] = done\n",
    "        self.ptr = (self.ptr + 1) % self.max_size\n",
    "        self.size = min(self.size + 1, self.max_size)\n",
    "\n",
    "    def sample_batch(self) -> Dict[str, np.ndarray]:\n",
    "        idxs = np.random.choice(self.size, size=self.batch_size, replace=False)\n",
    "        return dict(obs=self.obs_buf[idxs],\n",
    "                    next_obs=self.next_obs_buf[idxs],\n",
    "                    acts=self.acts_buf[idxs],\n",
    "                    rews=self.rews_buf[idxs],\n",
    "                    done=self.done_buf[idxs])\n",
    "\n",
    "    def __len__(self) -> int:\n",
    "        return self.size"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Network\n",
    "\n",
    "We are going to use a simple network architecture with three fully connected layers and two non-linearity functions (ReLU)."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "metadata": {},
   "outputs": [],
   "source": [
    "class Network(nn.Module):\n",
    "    def __init__(self, in_dim: int, out_dim: int):\n",
    "        \"\"\"Initialization.\"\"\"\n",
    "        super(Network, self).__init__()\n",
    "\n",
    "        self.layers = nn.Sequential(\n",
    "            nn.Linear(in_dim, 128), \n",
    "            nn.ReLU(),\n",
    "            nn.Linear(128, 128), \n",
    "            nn.ReLU(), \n",
    "            nn.Linear(128, out_dim)\n",
    "        )\n",
    "\n",
    "    def forward(self, x: torch.Tensor) -> torch.Tensor:\n",
    "        \"\"\"Forward method implementation.\"\"\"\n",
    "        return self.layers(x)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## DQN Agent\n",
    "\n",
    "Here is a summary of DQNAgent class.\n",
    "\n",
    "| Method           | Note                                                 |\n",
    "| ---              | ---                                                  |\n",
    "|select_action     | select an action from the input state.               |\n",
    "|step              | take an action and return the response of the env.   |\n",
    "|compute_dqn_loss  | return dqn loss.                                     |\n",
    "|update_model      | update the model by gradient descent.                |\n",
    "|target_hard_update| hard update from the local model to the target model.|\n",
    "|train             | train the agent during num_frames.                   |\n",
    "|test              | test the agent (1 episode).                          |\n",
    "|plot              | plot the training progresses.                        |\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "metadata": {},
   "outputs": [],
   "source": [
    "class DQNAgent:\n",
    "    \"\"\"DQN Agent interacting with environment.\n",
    "    \n",
    "    Attribute:\n",
    "        env (gym.Env): openAI Gym environment\n",
    "        memory (ReplayBuffer): replay memory to store transitions\n",
    "        batch_size (int): batch size for sampling\n",
    "        epsilon (float): parameter for epsilon greedy policy\n",
    "        epsilon_decay (float): step size to decrease epsilon\n",
    "        max_epsilon (float): max value of epsilon\n",
    "        min_epsilon (float): min value of epsilon\n",
    "        target_update (int): period for target model's hard update\n",
    "        gamma (float): discount factor\n",
    "        dqn (Network): model to train and select actions\n",
    "        dqn_target (Network): target model to update\n",
    "        optimizer (torch.optim): optimizer for training dqn\n",
    "        transition (list): transition information including \n",
    "                           state, action, reward, next_state, done\n",
    "    \"\"\"\n",
    "\n",
    "    def __init__(\n",
    "        self, \n",
    "        env: gym.Env,\n",
    "        memory_size: int,\n",
    "        batch_size: int,\n",
    "        target_update: int,\n",
    "        epsilon_decay: float,\n",
    "        max_epsilon: float = 1.0,\n",
    "        min_epsilon: float = 0.1,\n",
    "        gamma: float = 0.99,\n",
    "    ):\n",
    "        \"\"\"Initialization.\n",
    "        \n",
    "        Args:\n",
    "            env (gym.Env): openAI Gym environment\n",
    "            memory_size (int): length of memory\n",
    "            batch_size (int): batch size for sampling\n",
    "            target_update (int): period for target model's hard update\n",
    "            epsilon_decay (float): step size to decrease epsilon\n",
    "            lr (float): learning rate\n",
    "            max_epsilon (float): max value of epsilon\n",
    "            min_epsilon (float): min value of epsilon\n",
    "            gamma (float): discount factor\n",
    "        \"\"\"\n",
    "        obs_dim = env.observation_space.shape[0]\n",
    "        action_dim = env.action_space.n\n",
    "        \n",
    "        self.env = env\n",
    "        self.memory = ReplayBuffer(obs_dim, memory_size, batch_size)\n",
    "        self.batch_size = batch_size\n",
    "        self.epsilon = max_epsilon\n",
    "        self.epsilon_decay = epsilon_decay\n",
    "        self.max_epsilon = max_epsilon\n",
    "        self.min_epsilon = min_epsilon\n",
    "        self.target_update = target_update\n",
    "        self.gamma = gamma\n",
    "        \n",
    "        # device: cpu / gpu\n",
    "        self.device = torch.device(\n",
    "            \"cuda\" if torch.cuda.is_available() else \"cpu\"\n",
    "        )\n",
    "        print(self.device)\n",
    "\n",
    "        # networks: dqn, dqn_target\n",
    "        self.dqn = Network(obs_dim, action_dim).to(self.device)\n",
    "        self.dqn_target = Network(obs_dim, action_dim).to(self.device)\n",
    "        self.dqn_target.load_state_dict(self.dqn.state_dict())\n",
    "        self.dqn_target.eval()\n",
    "        \n",
    "        # optimizer\n",
    "        self.optimizer = optim.Adam(self.dqn.parameters())\n",
    "\n",
    "        # transition to store in memory\n",
    "        self.transition = list()\n",
    "        \n",
    "        # mode: train / test\n",
    "        self.is_test = False\n",
    "\n",
    "    def select_action(self, state: np.ndarray) -> np.ndarray:\n",
    "        \"\"\"Select an action from the input state.\"\"\"\n",
    "        # epsilon greedy policy\n",
    "        if self.epsilon > np.random.random():\n",
    "            selected_action = self.env.action_space.sample()\n",
    "        else:\n",
    "            selected_action = self.dqn(\n",
    "                torch.FloatTensor(state).to(self.device)\n",
    "            ).argmax()\n",
    "            selected_action = selected_action.detach().cpu().numpy()\n",
    "        \n",
    "        if not self.is_test:\n",
    "            self.transition = [state, selected_action]\n",
    "        \n",
    "        return selected_action\n",
    "\n",
    "    def step(self, action: np.ndarray) -> Tuple[np.ndarray, np.float64, bool]:\n",
    "        \"\"\"Take an action and return the response of the env.\"\"\"\n",
    "        next_state, reward, done, _ = self.env.step(action)\n",
    "\n",
    "        if not self.is_test:\n",
    "            self.transition += [reward, next_state, done]\n",
    "            self.memory.store(*self.transition)\n",
    "    \n",
    "        return next_state, reward, done\n",
    "\n",
    "    def update_model(self) -> torch.Tensor:\n",
    "        \"\"\"Update the model by gradient descent.\"\"\"\n",
    "        samples = self.memory.sample_batch()\n",
    "\n",
    "        loss = self._compute_dqn_loss(samples)\n",
    "\n",
    "        self.optimizer.zero_grad()\n",
    "        loss.backward()\n",
    "        # gradient clipping\n",
    "        # https://pytorch.org/docs/stable/nn.html#torch.nn.utils.clip_grad_norm_\n",
    "        clip_grad_norm_(self.dqn.parameters(), 1.0, norm_type=1)\n",
    "        self.optimizer.step()\n",
    "\n",
    "        return loss.item()\n",
    "        \n",
    "    def train(self, num_frames: int, plotting_interval: int = 200):\n",
    "        \"\"\"Train the agent.\"\"\"\n",
    "        self.is_test = False\n",
    "        \n",
    "        state = self.env.reset()\n",
    "        update_cnt = 0\n",
    "        epsilons = []\n",
    "        losses = []\n",
    "        scores = []\n",
    "        score = 0\n",
    "\n",
    "        for frame_idx in range(1, num_frames + 1):\n",
    "            action = self.select_action(state)\n",
    "            next_state, reward, done = self.step(action)\n",
    "\n",
    "            state = next_state\n",
    "            score += reward\n",
    "\n",
    "            # if episode ends\n",
    "            if done:\n",
    "                state = env.reset()\n",
    "                scores.append(score)\n",
    "                score = 0\n",
    "\n",
    "            # if training is ready\n",
    "            if len(self.memory) >= self.batch_size:\n",
    "                loss = self.update_model()\n",
    "                losses.append(loss)\n",
    "                update_cnt += 1\n",
    "                \n",
    "                # linearly decrease epsilon\n",
    "                self.epsilon = max(\n",
    "                    self.min_epsilon, self.epsilon - (\n",
    "                        self.max_epsilon - self.min_epsilon\n",
    "                    ) * self.epsilon_decay\n",
    "                )\n",
    "                epsilons.append(self.epsilon)\n",
    "                \n",
    "                # if hard update is needed\n",
    "                if update_cnt % self.target_update == 0:\n",
    "                    self._target_hard_update()\n",
    "\n",
    "            # plotting\n",
    "            if frame_idx % plotting_interval == 0:\n",
    "                self._plot(frame_idx, scores, losses, epsilons)\n",
    "                \n",
    "        self.env.close()\n",
    "                \n",
    "    def test(self) -> List[np.ndarray]:\n",
    "        \"\"\"Test the agent.\"\"\"\n",
    "        self.is_test = True\n",
    "        \n",
    "        state = self.env.reset()\n",
    "        done = False\n",
    "        score = 0\n",
    "        \n",
    "        frames = []\n",
    "        while not done:\n",
    "            frames.append(self.env.render(mode=\"rgb_array\"))\n",
    "            action = self.select_action(state)\n",
    "            next_state, reward, done = self.step(action)\n",
    "\n",
    "            state = next_state\n",
    "            score += reward\n",
    "        \n",
    "        print(\"score: \", score)\n",
    "        self.env.close()\n",
    "        \n",
    "        return frames\n",
    "\n",
    "    def _compute_dqn_loss(self, samples: Dict[str, np.ndarray]) -> torch.Tensor:\n",
    "        \"\"\"Return dqn loss.\"\"\"\n",
    "        device = self.device  # for shortening the following lines\n",
    "        state = torch.FloatTensor(samples[\"obs\"]).to(device)\n",
    "        next_state = torch.FloatTensor(samples[\"next_obs\"]).to(device)\n",
    "        action = torch.LongTensor(samples[\"acts\"].reshape(-1, 1)).to(device)\n",
    "        reward = torch.FloatTensor(samples[\"rews\"].reshape(-1, 1)).to(device)\n",
    "        done = torch.FloatTensor(samples[\"done\"].reshape(-1, 1)).to(device)\n",
    "\n",
    "        # G_t   = r + gamma * v(s_{t+1})  if state != Terminal\n",
    "        #       = r                       otherwise\n",
    "        curr_q_value = self.dqn(state).gather(1, action)\n",
    "        next_q_value = self.dqn_target(\n",
    "            next_state\n",
    "        ).max(dim=1, keepdim=True)[0].detach()\n",
    "        mask = 1 - done\n",
    "        target = (reward + self.gamma * next_q_value * mask).to(self.device)\n",
    "\n",
    "        # calculate dqn loss\n",
    "        loss = ((target - curr_q_value).pow(2)).mean()\n",
    "\n",
    "        return loss\n",
    "\n",
    "    def _target_hard_update(self):\n",
    "        \"\"\"Hard update: target <- local.\"\"\"\n",
    "        self.dqn_target.load_state_dict(self.dqn.state_dict())\n",
    "                \n",
    "    def _plot(\n",
    "        self, \n",
    "        frame_idx: int, \n",
    "        scores: List[float], \n",
    "        losses: List[float], \n",
    "        epsilons: List[float],\n",
    "    ):\n",
    "        \"\"\"Plot the training progresses.\"\"\"\n",
    "        clear_output(True)\n",
    "        plt.figure(figsize=(20, 5))\n",
    "        plt.subplot(131)\n",
    "        plt.title('frame %s. score: %s' % (frame_idx, np.mean(scores[-10:])))\n",
    "        plt.plot(scores)\n",
    "        plt.subplot(132)\n",
    "        plt.title('loss')\n",
    "        plt.plot(losses)\n",
    "        plt.subplot(133)\n",
    "        plt.title('epsilons')\n",
    "        plt.plot(epsilons)\n",
    "        plt.show()"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Environment\n",
    "\n",
    "You can see the [code](https://github.com/openai/gym/blob/master/gym/envs/classic_control/cartpole.py) and [configurations](https://github.com/openai/gym/blob/master/gym/envs/__init__.py#L53) of CartPole-v0 from OpenAI's repository."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 6,
   "metadata": {},
   "outputs": [],
   "source": [
    "# environment\n",
    "env_id = \"CartPole-v0\"\n",
    "env = gym.make(env_id)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Set random seed"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 7,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "[777]"
      ]
     },
     "execution_count": 7,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "seed = 777\n",
    "\n",
    "def seed_torch(seed):\n",
    "    torch.manual_seed(seed)\n",
    "    if torch.backends.cudnn.enabled:\n",
    "        torch.backends.cudnn.benchmark = False\n",
    "        torch.backends.cudnn.deterministic = True\n",
    "\n",
    "np.random.seed(seed)\n",
    "seed_torch(seed)\n",
    "env.seed(seed)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Initialize"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 8,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "cuda\n"
     ]
    }
   ],
   "source": [
    "# parameters\n",
    "num_frames = 10000\n",
    "memory_size = 1000\n",
    "batch_size = 32\n",
    "target_update = 200\n",
    "epsilon_decay = 1 / 2000\n",
    "\n",
    "agent = DQNAgent(env, memory_size, batch_size, target_update, epsilon_decay)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Train"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 9,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "image/png": "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\n",
      "text/plain": [
       "<Figure size 1440x360 with 3 Axes>"
      ]
     },
     "metadata": {
      "needs_background": "light"
     },
     "output_type": "display_data"
    }
   ],
   "source": [
    "agent.train(num_frames)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Test\n",
    "\n",
    "Run the trained agent (1 episode)."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 10,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "score:  192.0\n"
     ]
    }
   ],
   "source": [
    "frames = agent.test()"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Render"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 11,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/html": [
       "\n",
       "<script language=\"javascript\">\n",
       "  /* Define the Animation class */\n",
       "  function Animation(frames, img_id, slider_id, interval, loop_select_id){\n",
       "    this.img_id = img_id;\n",
       "    this.slider_id = slider_id;\n",
       "    this.loop_select_id = loop_select_id;\n",
       "    this.interval = interval;\n",
       "    this.current_frame = 0;\n",
       "    this.direction = 0;\n",
       "    this.timer = null;\n",
       "    this.frames = new Array(frames.length);\n",
       "\n",
       "    for (var i=0; i<frames.length; i++)\n",
       "    {\n",
       "     this.frames[i] = new Image();\n",
       "     this.frames[i].src = frames[i];\n",
       "    }\n",
       "    document.getElementById(this.slider_id).max = this.frames.length - 1;\n",
       "    this.set_frame(this.current_frame);\n",
       "  }\n",
       "\n",
       "  Animation.prototype.get_loop_state = function(){\n",
       "    var button_group = document[this.loop_select_id].state;\n",
       "    for (var i = 0; i < button_group.length; i++) {\n",
       "        var button = button_group[i];\n",
       "        if (button.checked) {\n",
       "            return button.value;\n",
       "        }\n",
       "    }\n",
       "    return undefined;\n",
       "  }\n",
       "\n",
       "  Animation.prototype.set_frame = function(frame){\n",
       "    this.current_frame = frame;\n",
       "    document.getElementById(this.img_id).src = this.frames[this.current_frame].src;\n",
       "    document.getElementById(this.slider_id).value = this.current_frame;\n",
       "  }\n",
       "\n",
       "  Animation.prototype.next_frame = function()\n",
       "  {\n",
       "    this.set_frame(Math.min(this.frames.length - 1, this.current_frame + 1));\n",
       "  }\n",
       "\n",
       "  Animation.prototype.previous_frame = function()\n",
       "  {\n",
       "    this.set_frame(Math.max(0, this.current_frame - 1));\n",
       "  }\n",
       "\n",
       "  Animation.prototype.first_frame = function()\n",
       "  {\n",
       "    this.set_frame(0);\n",
       "  }\n",
       "\n",
       "  Animation.prototype.last_frame = function()\n",
       "  {\n",
       "    this.set_frame(this.frames.length - 1);\n",
       "  }\n",
       "\n",
       "  Animation.prototype.slower = function()\n",
       "  {\n",
       "    this.interval /= 0.7;\n",
       "    if(this.direction > 0){this.play_animation();}\n",
       "    else if(this.direction < 0){this.reverse_animation();}\n",
       "  }\n",
       "\n",
       "  Animation.prototype.faster = function()\n",
       "  {\n",
       "    this.interval *= 0.7;\n",
       "    if(this.direction > 0){this.play_animation();}\n",
       "    else if(this.direction < 0){this.reverse_animation();}\n",
       "  }\n",
       "\n",
       "  Animation.prototype.anim_step_forward = function()\n",
       "  {\n",
       "    this.current_frame += 1;\n",
       "    if(this.current_frame < this.frames.length){\n",
       "      this.set_frame(this.current_frame);\n",
       "    }else{\n",
       "      var loop_state = this.get_loop_state();\n",
       "      if(loop_state == \"loop\"){\n",
       "        this.first_frame();\n",
       "      }else if(loop_state == \"reflect\"){\n",
       "        this.last_frame();\n",
       "        this.reverse_animation();\n",
       "      }else{\n",
       "        this.pause_animation();\n",
       "        this.last_frame();\n",
       "      }\n",
       "    }\n",
       "  }\n",
       "\n",
       "  Animation.prototype.anim_step_reverse = function()\n",
       "  {\n",
       "    this.current_frame -= 1;\n",
       "    if(this.current_frame >= 0){\n",
       "      this.set_frame(this.current_frame);\n",
       "    }else{\n",
       "      var loop_state = this.get_loop_state();\n",
       "      if(loop_state == \"loop\"){\n",
       "        this.last_frame();\n",
       "      }else if(loop_state == \"reflect\"){\n",
       "        this.first_frame();\n",
       "        this.play_animation();\n",
       "      }else{\n",
       "        this.pause_animation();\n",
       "        this.first_frame();\n",
       "      }\n",
       "    }\n",
       "  }\n",
       "\n",
       "  Animation.prototype.pause_animation = function()\n",
       "  {\n",
       "    this.direction = 0;\n",
       "    if (this.timer){\n",
       "      clearInterval(this.timer);\n",
       "      this.timer = null;\n",
       "    }\n",
       "  }\n",
       "\n",
       "  Animation.prototype.play_animation = function()\n",
       "  {\n",
       "    this.pause_animation();\n",
       "    this.direction = 1;\n",
       "    var t = this;\n",
       "    if (!this.timer) this.timer = setInterval(function(){t.anim_step_forward();}, this.interval);\n",
       "  }\n",
       "\n",
       "  Animation.prototype.reverse_animation = function()\n",
       "  {\n",
       "    this.pause_animation();\n",
       "    this.direction = -1;\n",
       "    var t = this;\n",
       "    if (!this.timer) this.timer = setInterval(function(){t.anim_step_reverse();}, this.interval);\n",
       "  }\n",
       "</script>\n",
       "\n",
       "<div class=\"animation\" align=\"center\">\n",
       "    <img id=\"_anim_imgOWMFIEJHUXHOIMDU\">\n",
       "    <br>\n",
       "    <input id=\"_anim_sliderOWMFIEJHUXHOIMDU\" type=\"range\" style=\"width:350px\" name=\"points\" min=\"0\" max=\"1\" step=\"1\" value=\"0\" onchange=\"animOWMFIEJHUXHOIMDU.set_frame(parseInt(this.value));\"></input>\n",
       "    <br>\n",
       "    <button onclick=\"animOWMFIEJHUXHOIMDU.slower()\">&#8211;</button>\n",
       "    <button onclick=\"animOWMFIEJHUXHOIMDU.first_frame()\"><img class=\"anim_icon\" src=\"\"></button>\n",
       "    <button onclick=\"animOWMFIEJHUXHOIMDU.previous_frame()\"><img class=\"anim_icon\" src=\"\"></button>\n",
       "    <button onclick=\"animOWMFIEJHUXHOIMDU.reverse_animation()\"><img class=\"anim_icon\" src=\"\"></button>\n",
       "    <button onclick=\"animOWMFIEJHUXHOIMDU.pause_animation()\"><img class=\"anim_icon\" src=\"\"></button>\n",
       "    <button onclick=\"animOWMFIEJHUXHOIMDU.play_animation()\"><img class=\"anim_icon\" src=\"\"></button>\n",
       "    <button onclick=\"animOWMFIEJHUXHOIMDU.next_frame()\"><img class=\"anim_icon\" src=\"\"></button>\n",
       "    <button onclick=\"animOWMFIEJHUXHOIMDU.last_frame()\"><img class=\"anim_icon\" src=\"\"></button>\n",
       "    <button onclick=\"animOWMFIEJHUXHOIMDU.faster()\">+</button>\n",
       "  <form action=\"#n\" name=\"_anim_loop_selectOWMFIEJHUXHOIMDU\" class=\"anim_control\">\n",
       "    <input type=\"radio\" name=\"state\" value=\"once\" > Once </input>\n",
       "    <input type=\"radio\" name=\"state\" value=\"loop\" checked> Loop </input>\n",
       "    <input type=\"radio\" name=\"state\" value=\"reflect\" > Reflect </input>\n",
       "  </form>\n",
       "</div>\n",
       "\n",
       "\n",
       "<script language=\"javascript\">\n",
       "  /* Instantiate the Animation class. */\n",
       "  /* The IDs given should match those used in the template above. */\n",
       "  (function() {\n",
       "    var img_id = \"_anim_imgOWMFIEJHUXHOIMDU\";\n",
       "    var slider_id = \"_anim_sliderOWMFIEJHUXHOIMDU\";\n",
       "    var loop_select_id = \"_anim_loop_selectOWMFIEJHUXHOIMDU\";\n",
       "    var frames = new Array(0);\n",
       "    \n",
       "  frames[0] = \"\"\n",
       "  frames[1] = \"\"\n",
       "  frames[2] = \"\"\n",
       "  frames[3] = \"\"\n",
       "  frames[4] = \"\"\n",
       "  frames[5] = \"\"\n",
       "  frames[6] = \"\"\n",
       "  frames[7] = \"\"\n",
       "  frames[8] = \"\"\n",
       "  frames[9] = \"\"\n",
       "  frames[10] = \"\"\n",
       "  frames[11] = \"\"\n",
       "  frames[12] = \"\"\n",
       "  frames[13] = \"\"\n",
       "  frames[14] = \"\"\n",
       "  frames[15] = \"\"\n",
       "  frames[16] = \"\"\n",
       "  frames[17] = \"\"\n",
       "  frames[18] = \"\"\n",
       "  frames[19] = \"\"\n",
       "  frames[20] = \"\"\n",
       "  frames[21] = \"\"\n",
       "  frames[22] = \"\"\n",
       "  frames[23] = \"\"\n",
       "  frames[24] = \"\"\n",
       "  frames[25] = \"\"\n",
       "  frames[26] = \"\"\n",
       "  frames[27] = \"\"\n",
       "  frames[28] = \"\"\n",
       "  frames[29] = \"\"\n",
       "  frames[30] = \"\"\n",
       "  frames[31] = \"\"\n",
       "  frames[32] = \"\"\n",
       "  frames[33] = \"\"\n",
       "  frames[34] = \"\"\n",
       "  frames[35] = \"\"\n",
       "  frames[36] = \"\"\n",
       "  frames[37] = \"\"\n",
       "  frames[38] = \"\"\n",
       "  frames[39] = \"\"\n",
       "  frames[40] = \"\"\n",
       "  frames[41] = \"\"\n",
       "  frames[42] = \"\"\n",
       "  frames[43] = \"\"\n",
       "  frames[44] = \"\"\n",
       "  frames[45] = \"\"\n",
       "  frames[46] = \"\"\n",
       "  frames[47] = \"\"\n",
       "  frames[48] = \"\"\n",
       "  frames[49] = \"\"\n",
       "  frames[50] = \"\"\n",
       "  frames[51] = \"\"\n",
       "  frames[52] = \"\"\n",
       "  frames[53] = \"\"\n",
       "  frames[54] = \"\"\n",
       "  frames[55] = \"\"\n",
       "  frames[56] = \"\"\n",
       "  frames[57] = \"\"\n",
       "  frames[58] = \"\"\n",
       "  frames[59] = \"\"\n",
       "  frames[60] = \"\"\n",
       "  frames[61] = \"\"\n",
       "  frames[62] = \"\"\n",
       "  frames[63] = \"\"\n",
       "  frames[64] = \"\"\n",
       "  frames[65] = \"\"\n",
       "  frames[66] = \"\"\n",
       "  frames[67] = \"\"\n",
       "  frames[68] = \"\"\n",
       "  frames[69] = \"\"\n",
       "  frames[70] = \"\"\n",
       "  frames[71] = \"\"\n",
       "  frames[72] = \"\"\n",
       "  frames[73] = \"\"\n",
       "  frames[74] = \"\"\n",
       "  frames[75] = \"\"\n",
       "  frames[76] = \"\"\n",
       "  frames[77] = \"\"\n",
       "  frames[78] = \"\"\n",
       "  frames[79] = \"\"\n",
       "  frames[80] = \"\"\n",
       "  frames[81] = \"\"\n",
       "  frames[82] = \"\"\n",
       "  frames[83] = \"\"\n",
       "  frames[84] = \"\"\n",
       "  frames[85] = \"\"\n",
       "  frames[86] = \"\"\n",
       "  frames[87] = \"\"\n",
       "  frames[88] = \"\"\n",
       "  frames[89] = \"\"\n",
       "  frames[90] = \"\"\n",
       "  frames[91] = \"\"\n",
       "  frames[92] = \"\"\n",
       "  frames[93] = \"\"\n",
       "  frames[94] = \"\"\n",
       "  frames[95] = \"\"\n",
       "  frames[96] = \"\"\n",
       "  frames[97] = \"\"\n",
       "  frames[98] = \"\"\n",
       "  frames[99] = \"\"\n",
       "  frames[100] = \"\"\n",
       "  frames[101] = \"\"\n",
       "  frames[102] = \"\"\n",
       "  frames[103] = \"\"\n",
       "  frames[104] = \"\"\n",
       "  frames[105] = \"\"\n",
       "  frames[106] = \"\"\n",
       "  frames[107] = \"\"\n",
       "  frames[108] = \"\"\n",
       "  frames[109] = \"\"\n",
       "  frames[110] = \"\"\n",
       "  frames[111] = \"\"\n",
       "  frames[112] = \"\"\n",
       "  frames[113] = \"\"\n",
       "  frames[114] = \"\"\n",
       "  frames[115] = \"\"\n",
       "  frames[116] = \"\"\n",
       "  frames[117] = \"\"\n",
       "  frames[118] = \"\"\n",
       "  frames[119] = \"\"\n",
       "  frames[120] = \"\"\n",
       "  frames[121] = \"\"\n",
       "  frames[122] = \"\"\n",
       "  frames[123] = \"\"\n",
       "  frames[124] = \"\"\n",
       "  frames[125] = \"\"\n",
       "  frames[126] = \"\"\n",
       "  frames[127] = \"\"\n",
       "  frames[128] = \"\"\n",
       "  frames[129] = \"\"\n",
       "  frames[130] = \"\"\n",
       "  frames[131] = \"\"\n",
       "  frames[132] = \"\"\n",
       "  frames[133] = \"\"\n",
       "  frames[134] = \"\"\n",
       "  frames[135] = \"\"\n",
       "  frames[136] = \"\"\n",
       "  frames[137] = \"\"\n",
       "  frames[138] = \"\"\n",
       "  frames[139] = \"\"\n",
       "  frames[140] = \"\"\n",
       "  frames[141] = \"\"\n",
       "  frames[142] = \"\"\n",
       "  frames[143] = \"\"\n",
       "  frames[144] = \"\"\n",
       "  frames[145] = \"\"\n",
       "  frames[146] = \"\"\n",
       "  frames[147] = \"\"\n",
       "  frames[148] = \"\"\n",
       "  frames[149] = \"\"\n",
       "  frames[150] = \"\"\n",
       "  frames[151] = \"\"\n",
       "  frames[152] = \"\"\n",
       "  frames[153] = \"\"\n",
       "  frames[154] = \"\"\n",
       "  frames[155] = \"\"\n",
       "  frames[156] = \"\"\n",
       "  frames[157] = \"\"\n",
       "  frames[158] = \"\"\n",
       "  frames[159] = \"\"\n",
       "  frames[160] = \"\"\n",
       "  frames[161] = \"\"\n",
       "  frames[162] = \"\"\n",
       "  frames[163] = \"\"\n",
       "  frames[164] = \"\"\n",
       "  frames[165] = \"\"\n",
       "  frames[166] = \"\"\n",
       "  frames[167] = \"\"\n",
       "  frames[168] = \"\"\n",
       "  frames[169] = \"\"\n",
       "  frames[170] = \"\"\n",
       "  frames[171] = \"\"\n",
       "  frames[172] = \"\"\n",
       "  frames[173] = \"\"\n",
       "  frames[174] = \"\"\n",
       "  frames[175] = \"\"\n",
       "  frames[176] = \"\"\n",
       "  frames[177] = \"\"\n",
       "  frames[178] = \"\"\n",
       "  frames[179] = \"\"\n",
       "  frames[180] = \"\"\n",
       "  frames[181] = \"\"\n",
       "  frames[182] = \"\"\n",
       "  frames[183] = \"\"\n",
       "  frames[184] = \"\"\n",
       "  frames[185] = \"\"\n",
       "  frames[186] = \"\"\n",
       "  frames[187] = \"\"\n",
       "  frames[188] = \"\"\n",
       "  frames[189] = \"\"\n",
       "  frames[190] = \"\"\n",
       "  frames[191] = \"\"\n",
       "\n",
       "\n",
       "    /* set a timeout to make sure all the above elements are created before\n",
       "       the object is initialized. */\n",
       "    setTimeout(function() {\n",
       "        animOWMFIEJHUXHOIMDU = new Animation(frames, img_id, slider_id, 50, loop_select_id);\n",
       "    }, 0);\n",
       "  })()\n",
       "</script>\n"
      ],
      "text/plain": [
       "<IPython.core.display.HTML object>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "# Imports specifically so we can render outputs in Colab.\n",
    "from matplotlib import animation\n",
    "from JSAnimation.IPython_display import display_animation\n",
    "from IPython.display import display\n",
    "\n",
    "\n",
    "def display_frames_as_gif(frames):\n",
    "    \"\"\"Displays a list of frames as a gif, with controls.\"\"\"\n",
    "    patch = plt.imshow(frames[0])\n",
    "    plt.axis('off')\n",
    "\n",
    "    def animate(i):\n",
    "        patch.set_data(frames[i])\n",
    "\n",
    "    anim = animation.FuncAnimation(\n",
    "        plt.gcf(), animate, frames = len(frames), interval=50\n",
    "    )\n",
    "    display(display_animation(anim, default_mode='loop'))\n",
    "    \n",
    "        \n",
    "# display \n",
    "display_frames_as_gif(frames)"
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.7.3"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 2
}
